package pers.burgess.xml.handler;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class EnhanceHandler<T> extends DefaultHandler {

    private T currentTmp;
    private String currentElementName;

    private Class<?> cls;
    private List<T> list;

    public EnhanceHandler(Class<?> cls) {
        this.cls = cls;
    }

    public List<T> getList() {
        return this.list;
    }

    @Override
    public void startDocument() throws SAXException {
        this.list = new ArrayList<T>();
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        if (qName.toUpperCase().equals(cls.getName().substring(cls.getName().lastIndexOf(".") + 1).toUpperCase())){
            try {
				currentTmp = (T) cls.newInstance();
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
        } else {
            currentElementName = qName;
        }
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        String setMethodName = "set" + currentElementName.substring(0, 1).toUpperCase() + currentElementName.substring(1);
        String getMethodName = "get" + currentElementName.substring(0, 1).toUpperCase() + currentElementName.substring(1);
        String text = new String(ch).substring(start, start + length);
        if (!(text.replaceAll("\r|\n|\\s", "").isEmpty())) {
        	try {
                Class<?> fieldType = cls.getDeclaredMethod(getMethodName).getReturnType();
                Method setMethod = cls.getDeclaredMethod(setMethodName, fieldType);
                switch(fieldType.getName().toUpperCase().substring(fieldType.getName().lastIndexOf(".") + 1)) {
    	            case "INT":
    	            case "INTEGER":
    	            	setMethod.invoke(currentTmp, Integer.valueOf(text));
    	            	break;
    	            case "STRING":
    	            	setMethod.invoke(currentTmp, text);
    	            	break;
    	            case "DOUBLE":
    	            	setMethod.invoke(currentTmp, Double.valueOf(text));
    	            	break;
    	            case "FLOAT":
    	            	setMethod.invoke(currentTmp, Float.valueOf(text));
    	            	break;
    	            case "CHAR":
    	            	setMethod.invoke(currentTmp, text.charAt(0));
    	            	break;
    	            case "BYTE":
    	            	setMethod.invoke(currentTmp, text.getBytes()[0]);
    	            	break;
    	            case "LONG":
    	            	setMethod.invoke(currentTmp, Long.valueOf(text));
    	            	break;
    	            case "SHORT":
    	            	setMethod.invoke(currentTmp, Short.valueOf(text));
    	            	break;
    	            	default:
    	            		setMethod.invoke(currentTmp, (Object) text);
    	            		break;
                }
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if (qName.toUpperCase().equals(cls.getName().substring(cls.getName().lastIndexOf(".") + 1).toUpperCase())){
            this.list.add(currentTmp);
            currentTmp = null;
        }
    }

}
